use thiserror::Error;

pub type IoErr = std::io::Error;
pub type XmlErr = serde_xml_rs::Error;
pub type SqlxErr = sqlx::Error;
pub type CborErr = serde_cbor::Error;

#[derive(Debug, Error)]
pub enum AppErr {

    #[error("io:{0}")]
    Io(#[from] IoErr),

    #[error("xml:{0}")]
    Xml(#[from] XmlErr),

    #[error("sqlx:{0}")]
    Sqlx(#[from] SqlxErr),

    #[error("cbor:{0}")]
    Cbor(#[from] CborErr),

    #[error("{0}")]
    Static(&'static str),

    #[error("{0}")]
    Dyn(String),
}

pub fn new_err<T>(msg: &'static str) -> Result<T, AppErr> {
    Err(AppErr::Static(msg))
}

pub fn new_str_err<T>(msg: String) -> Result<T, AppErr> {
    Err(AppErr::Dyn(msg))
}

pub trait ErrorWrap<T> {
    
    fn wrap(self) -> Result<T, AppErr>;
}

impl <T, E: std::error::Error> ErrorWrap<T> for Result<T, E> {

    fn wrap(self) -> Result<T, AppErr> {
        match self {
            Err(e) => Err(AppErr::Dyn(e.to_string())),
            Ok(v) => Ok(v)
        }
    }
} 


